<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>图片Base64转换工具</title>
    <style>
      * {
        box-sizing: border-box;
        margin: 0;
        padding: 0;
        font-family: 'SF Pro Display', 'PingFang SC', 'Helvetica Neue', Arial,
          sans-serif;
      }

      :root {
        --primary-bg: #e6e7ee;
        --secondary-bg: #ffffff;
        --shadow-light: #ffffff;
        --shadow-dark: #d1d9e6;
        --accent-color: #667eea;
        --accent-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        --success-color: #4ecdc4;
        --danger-color: #ff6b6b;
        --warning-color: #feca57;
        --text-primary: #2d3748;
        --text-secondary: #718096;
        --glass-bg: rgba(255, 255, 255, 0.25);
        --glass-border: rgba(255, 255, 255, 0.18);
      }

      body {
        background: var(--primary-bg);
        color: var(--text-primary);
        min-height: 100vh;
        padding: 20px;
        display: flex;
        flex-direction: column;
        align-items: center;
        transition: all 0.3s ease;
        animation: pageLoad 0.8s ease;
      }

      @keyframes pageLoad {
        from {
          opacity: 0;
          transform: translateY(20px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      .container {
        width: 100%;
        max-width: 1200px;
        background: var(--primary-bg);
        border-radius: 30px;
        padding: 40px;
        box-shadow: 20px 20px 60px var(--shadow-dark),
          -20px -20px 60px var(--shadow-light);
        margin-top: 20px;
        transition: all 0.3s ease;
        animation: containerFloat 1s ease 0.2s both;
      }

      @keyframes containerFloat {
        from {
          opacity: 0;
          transform: translateY(30px) scale(0.95);
        }
        to {
          opacity: 1;
          transform: translateY(0) scale(1);
        }
      }

      .container:hover {
        box-shadow: 25px 25px 70px var(--shadow-dark),
          -25px -25px 70px var(--shadow-light);
      }

      header {
        text-align: center;
        margin-bottom: 40px;
        padding: 30px;
        background: var(--primary-bg);
        border-radius: 25px;
        box-shadow: 10px 10px 20px var(--shadow-dark),
          -10px -10px 20px var(--shadow-light);
        animation: headerSlide 0.8s ease 0.4s both;
      }

      @keyframes headerSlide {
        from {
          opacity: 0;
          transform: translateY(-30px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      h1 {
        font-size: 3.2rem;
        margin-bottom: 15px;
        background: var(--accent-gradient);
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        background-clip: text;
        font-weight: 700;
        animation: titleGlow 3s ease-in-out infinite alternate;
      }

      @keyframes titleGlow {
        from {
          filter: brightness(1);
        }
        to {
          filter: brightness(1.2);
        }
      }

      .subtitle {
        font-size: 1.3rem;
        color: var(--text-secondary);
        margin-bottom: 30px;
        font-weight: 500;
      }

      .panels {
        display: flex;
        gap: 30px;
        margin-bottom: 40px;
        animation: panelsSlide 0.8s ease 0.6s both;
      }

      @keyframes panelsSlide {
        from {
          opacity: 0;
          transform: translateX(-20px);
        }
        to {
          opacity: 1;
          transform: translateX(0);
        }
      }

      .panel {
        flex: 1;
        background: var(--primary-bg);
        border-radius: 25px;
        padding: 30px;
        box-shadow: 12px 12px 24px var(--shadow-dark),
          -12px -12px 24px var(--shadow-light);
        transition: all 0.3s ease;
        position: relative;
        overflow: hidden;
      }

      .panel::before {
        content: '';
        position: absolute;
        top: 0;
        left: -100%;
        width: 100%;
        height: 100%;
        background: linear-gradient(
          90deg,
          transparent,
          rgba(255, 255, 255, 0.1),
          transparent
        );
        transition: left 0.8s;
      }

      .panel:hover::before {
        left: 100%;
      }

      .panel:hover {
        transform: translateY(-5px);
        box-shadow: 16px 16px 32px var(--shadow-dark),
          -16px -16px 32px var(--shadow-light);
      }

      .panel-title {
        font-size: 1.6rem;
        margin-bottom: 25px;
        color: var(--accent-color);
        display: flex;
        align-items: center;
        font-weight: 600;
      }

      .panel-title::before {
        content: attr(data-icon);
        margin-right: 12px;
        font-size: 1.8rem;
        animation: iconBounce 2s ease-in-out infinite;
      }

      @keyframes iconBounce {
        0%,
        100% {
          transform: scale(1);
        }
        50% {
          transform: scale(1.1);
        }
      }

      .file-upload {
        border: 3px dashed var(--accent-color);
        border-radius: 25px;
        padding: 50px 40px;
        text-align: center;
        transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
        margin-bottom: 25px;
        cursor: pointer;
        background: var(--primary-bg);
        box-shadow: inset 8px 8px 16px var(--shadow-dark),
          inset -8px -8px 16px var(--shadow-light);
        position: relative;
        overflow: hidden;
      }

      .file-upload:hover {
        border-color: var(--success-color);
        transform: translateY(-5px) scale(1.02);
        box-shadow: inset 10px 10px 20px var(--shadow-dark),
          inset -10px -10px 20px var(--shadow-light),
          0 15px 40px rgba(102, 126, 234, 0.25), 0 5px 15px rgba(0, 0, 0, 0.1);
      }

      .file-upload.dragover {
        border-color: var(--success-color);
        background: rgba(78, 205, 196, 0.05);
        transform: scale(1.05);
        box-shadow: inset 12px 12px 24px var(--shadow-dark),
          inset -12px -12px 24px var(--shadow-light),
          0 20px 50px rgba(78, 205, 196, 0.3);
        animation: dragPulse 1s ease-in-out infinite;
      }

      @keyframes dragPulse {
        0%,
        100% {
          border-color: var(--success-color);
        }
        50% {
          border-color: var(--accent-color);
        }
      }

      .file-upload-content {
        position: relative;
        z-index: 1;
      }

      .file-upload-icon {
        font-size: 3.5rem;
        margin-bottom: 20px;
        display: block;
        animation: iconFloat 3s ease-in-out infinite;
        filter: drop-shadow(0 4px 8px rgba(102, 126, 234, 0.2));
      }

      @keyframes iconFloat {
        0%,
        100% {
          transform: translateY(0);
        }
        50% {
          transform: translateY(-10px);
        }
      }

      .file-upload-text {
        font-size: 1.4rem;
        font-weight: 600;
        color: var(--text-primary);
        margin-bottom: 10px;
        background: var(--accent-gradient);
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        background-clip: text;
      }

      .file-upload-subtext {
        font-size: 1.1rem;
        color: var(--text-secondary);
        margin-bottom: 20px;
        font-weight: 500;
      }

      .file-upload-formats {
        font-size: 0.9rem;
        color: var(--accent-color);
        font-weight: 500;
        padding: 8px 16px;
        background: rgba(102, 126, 234, 0.1);
        border-radius: 20px;
        display: inline-block;
        margin-bottom: 20px;
      }

      .file-upload input[type='file'] {
        position: absolute;
        width: 100%;
        height: 100%;
        top: 0;
        left: 0;
        opacity: 0;
        cursor: pointer;
        z-index: 2;
      }

      .image-preview {
        width: 100%;
        background: var(--primary-bg);
        border-radius: 20px;
        overflow: hidden;
        margin-top: 20px;
        box-shadow: inset 10px 10px 20px var(--shadow-dark),
          inset -10px -10px 20px var(--shadow-light);
        transition: all 0.3s ease;
        text-align: center;
        padding: 20px;
      }

      .image-preview:hover {
        box-shadow: inset 12px 12px 24px var(--shadow-dark),
          inset -12px -12px 24px var(--shadow-light);
      }

      .preview-image {
        max-width: 100%;
        max-height: 300px;
        border-radius: 15px;
        box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
      }

      .base64-input {
        width: 100%;
        min-height: 200px;
        padding: 20px;
        background: var(--primary-bg);
        border: none;
        border-radius: 20px;
        color: var(--text-primary);
        font-size: 0.9rem;
        font-family: 'Courier New', monospace;
        box-shadow: inset 8px 8px 16px var(--shadow-dark),
          inset -8px -8px 16px var(--shadow-light);
        transition: all 0.3s ease;
        resize: vertical;
        margin-bottom: 20px;
      }

      .base64-input:focus {
        outline: none;
        box-shadow: inset 10px 10px 20px var(--shadow-dark),
          inset -10px -10px 20px var(--shadow-light),
          0 0 0 3px rgba(102, 126, 234, 0.2);
      }

      .base64-input::placeholder {
        color: var(--text-secondary);
        font-style: italic;
      }

      button {
        background: var(--primary-bg);
        color: var(--text-primary);
        border: none;
        padding: 14px 28px;
        border-radius: 15px;
        cursor: pointer;
        font-weight: 600;
        transition: all 0.3s ease;
        font-size: 1rem;
        flex-shrink: 0;
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light);
        position: relative;
        overflow: hidden;
        margin: 5px;
      }

      button::before {
        content: '';
        position: absolute;
        top: 0;
        left: -100%;
        width: 100%;
        height: 100%;
        background: linear-gradient(
          90deg,
          transparent,
          rgba(255, 255, 255, 0.2),
          transparent
        );
        transition: left 0.5s;
      }

      button:hover::before {
        left: 100%;
      }

      button:hover {
        transform: translateY(-3px);
        box-shadow: 12px 12px 24px var(--shadow-dark),
          -12px -12px 24px var(--shadow-light);
      }

      button:active {
        transform: translateY(0);
        box-shadow: inset 6px 6px 12px var(--shadow-dark),
          inset -6px -6px 12px var(--shadow-light);
      }

      button:disabled {
        opacity: 0.6;
        cursor: not-allowed;
        transform: none;
        box-shadow: 4px 4px 8px var(--shadow-dark),
          -4px -4px 8px var(--shadow-light);
      }

      .btn-primary {
        background: var(--accent-gradient);
        color: white;
        padding: 16px 32px;
        font-size: 1.1rem;
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light),
          inset 0 1px 0 rgba(255, 255, 255, 0.2);
      }

      .btn-primary:hover {
        box-shadow: 12px 12px 24px var(--shadow-dark),
          -12px -12px 24px var(--shadow-light),
          inset 0 1px 0 rgba(255, 255, 255, 0.2),
          0 0 30px rgba(102, 126, 234, 0.3);
      }

      .btn-success {
        background: linear-gradient(
          135deg,
          var(--success-color) 0%,
          #44a08d 100%
        );
        color: white;
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light),
          inset 0 1px 0 rgba(255, 255, 255, 0.2);
      }

      .btn-warning {
        background: linear-gradient(
          135deg,
          var(--warning-color) 0%,
          #ff9ff3 100%
        );
        color: white;
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light),
          inset 0 1px 0 rgba(255, 255, 255, 0.2);
      }

      .actions {
        display: flex;
        justify-content: center;
        gap: 15px;
        margin-top: 20px;
        flex-wrap: wrap;
      }

      .status-message {
        min-height: 35px;
        margin: 20px 0;
        color: var(--accent-color);
        font-weight: 600;
        font-size: 1.1rem;
        transition: all 0.3s ease;
        text-align: center;
      }

      .error-message {
        color: var(--danger-color);
        margin: 20px 0;
        min-height: 35px;
        font-weight: 600;
        font-size: 1.1rem;
        animation: errorShake 0.5s ease;
        text-align: center;
      }

      @keyframes errorShake {
        0%,
        100% {
          transform: translateX(0);
        }
        25% {
          transform: translateX(-5px);
        }
        75% {
          transform: translateX(5px);
        }
      }

      .result-section {
        margin-top: 30px;
        padding: 25px;
        background: var(--primary-bg);
        border-radius: 25px;
        box-shadow: 10px 10px 20px var(--shadow-dark),
          -10px -10px 20px var(--shadow-light);
        display: none;
      }

      .result-section.show {
        display: block;
        animation: resultSlide 0.5s ease;
      }

      @keyframes resultSlide {
        from {
          opacity: 0;
          transform: translateY(20px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      .instructions {
        background: var(--primary-bg);
        border-radius: 25px;
        padding: 30px;
        margin-top: 40px;
        box-shadow: 10px 10px 20px var(--shadow-dark),
          -10px -10px 20px var(--shadow-light);
        animation: instructionsSlide 0.8s ease 1.4s both;
      }

      @keyframes instructionsSlide {
        from {
          opacity: 0;
          transform: translateY(30px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      .instructions h3 {
        color: var(--accent-color);
        margin-bottom: 20px;
        font-size: 1.4rem;
        font-weight: 600;
      }

      .instructions ol {
        padding-left: 25px;
        margin-bottom: 20px;
      }

      .instructions li {
        margin-bottom: 12px;
        line-height: 1.7;
        color: var(--text-secondary);
        font-weight: 500;
      }

      .instructions p {
        color: var(--text-secondary);
        font-style: italic;
        font-weight: 500;
        padding: 15px;
        background: rgba(102, 126, 234, 0.1);
        border-radius: 15px;
        border-left: 4px solid var(--accent-color);
      }

      footer {
        margin-top: 40px;
        text-align: center;
        color: var(--text-secondary);
        font-size: 0.95rem;
        padding: 25px;
        background: var(--primary-bg);
        border-radius: 20px;
        box-shadow: 6px 6px 12px var(--shadow-dark),
          -6px -6px 12px var(--shadow-light);
        animation: footerFade 0.8s ease 1.6s both;
      }

      @keyframes footerFade {
        from {
          opacity: 0;
        }
        to {
          opacity: 1;
        }
      }

      .file-info {
        background: rgba(102, 126, 234, 0.1);
        border-radius: 15px;
        padding: 15px;
        margin: 15px 0;
        border-left: 4px solid var(--accent-color);
      }

      .file-info-item {
        display: flex;
        justify-content: space-between;
        margin-bottom: 8px;
        font-size: 0.9rem;
      }

      .file-info-label {
        color: var(--text-secondary);
        font-weight: 500;
      }

      .file-info-value {
        color: var(--text-primary);
        font-weight: 600;
      }

      @media (max-width: 768px) {
        .panels {
          flex-direction: column;
        }
        
        .container {
          padding: 20px;
        }
        
        h1 {
          font-size: 2.5rem;
        }
        
        .actions {
          flex-direction: column;
          align-items: center;
        }
      }
    </style>
  </head>
  <body>
    <div class="container">
      <header>
        <h1>🖼️ 图片Base64转换工具</h1>
        <p class="subtitle">支持图片转Base64编码和Base64解码为图片，完全在浏览器中处理，保护您的隐私</p>
      </header>

      <div class="panels">
        <!-- 图片转Base64面板 -->
        <div class="panel">
          <h2 class="panel-title" data-icon="📤">图片转Base64</h2>
          
          <div class="file-upload" id="imageUpload">
            <div class="file-upload-content">
              <span class="file-upload-icon">🖼️</span>
              <div class="file-upload-text">点击或拖拽上传图片</div>
              <div class="file-upload-subtext">支持多种图片格式</div>
              <div class="file-upload-formats">JPG, PNG, GIF, WEBP, BMP, SVG</div>
            </div>
            <input type="file" id="imageInput" accept="image/*" />
          </div>

          <div class="image-preview" id="imagePreview">
            <p style="color: var(--text-secondary); font-size: 1.1rem;">🖼️ 图片预览区</p>
          </div>

          <div class="actions">
            <button class="btn-primary" id="convertToBase64" disabled>🔄 转换为Base64</button>
            <button id="clearImage">🗑️ 清空</button>
          </div>
        </div>

        <!-- Base64转图片面板 -->
        <div class="panel">
          <h2 class="panel-title" data-icon="📥">Base64转图片</h2>
          
          <textarea 
            class="base64-input" 
            id="base64Input" 
            placeholder="请粘贴Base64编码字符串...\n\n支持以下格式：\n• ...\n• iVBORw0KGgoAAAANSUhEUgAA...（纯Base64字符串）"
          ></textarea>

          <div class="image-preview" id="base64Preview">
            <p style="color: var(--text-secondary); font-size: 1.1rem;">🖼️ 解码预览区</p>
          </div>

          <div class="actions">
            <button class="btn-primary" id="convertFromBase64" disabled>🔄 解码为图片</button>
            <button class="btn-success" id="downloadImage" disabled>📥 下载图片</button>
            <button id="clearBase64">🗑️ 清空</button>
          </div>
        </div>
      </div>

      <!-- 结果展示区域 -->
      <div class="result-section" id="resultSection">
        <h3 style="color: var(--accent-color); margin-bottom: 20px; text-align: center;">📋 转换结果</h3>
        <textarea 
          class="base64-input" 
          id="resultBase64" 
          readonly
          placeholder="Base64编码结果将显示在这里..."
        ></textarea>
        <div class="actions">
          <button class="btn-success" id="copyBase64">📋 复制Base64</button>
          <button class="btn-warning" id="downloadBase64">💾 下载为文本</button>
        </div>
      </div>

      <div class="status-message" id="statusMessage"></div>
      <div class="error-message" id="errorMessage"></div>

      <!-- 使用说明 -->
      <div class="instructions">
        <h3>📖 使用说明</h3>
        <ol>
          <li><strong>图片转Base64：</strong>点击或拖拽上传图片文件，支持JPG、PNG、GIF、WEBP、BMP、SVG等格式</li>
          <li><strong>Base64转图片：</strong>在右侧文本框中粘贴Base64编码字符串，支持带前缀和纯Base64格式</li>
          <li><strong>预览功能：</strong>转换前后都可以实时预览图片效果</li>
          <li><strong>下载保存：</strong>可以下载转换后的图片或Base64文本文件</li>
          <li><strong>隐私保护：</strong>所有处理都在浏览器本地完成，不会上传到服务器</li>
        </ol>
        <p>💡 提示：Base64编码会增加约33%的文件大小，适合用于网页内嵌小图片或数据传输。</p>
      </div>

      <footer>
        <p>🔒 完全本地处理，保护您的隐私安全 | 💻 支持所有现代浏览器</p>
      </footer>
    </div>

    <script>
      // 全局变量
      let currentImageFile = null;
      let currentBase64 = '';
      let decodedImageBlob = null;

      // DOM元素
      const imageUpload = document.getElementById('imageUpload');
      const imageInput = document.getElementById('imageInput');
      const imagePreview = document.getElementById('imagePreview');
      const base64Input = document.getElementById('base64Input');
      const base64Preview = document.getElementById('base64Preview');
      const convertToBase64Btn = document.getElementById('convertToBase64');
      const convertFromBase64Btn = document.getElementById('convertFromBase64');
      const downloadImageBtn = document.getElementById('downloadImage');
      const clearImageBtn = document.getElementById('clearImage');
      const clearBase64Btn = document.getElementById('clearBase64');
      const resultSection = document.getElementById('resultSection');
      const resultBase64 = document.getElementById('resultBase64');
      const copyBase64Btn = document.getElementById('copyBase64');
      const downloadBase64Btn = document.getElementById('downloadBase64');
      const statusMessage = document.getElementById('statusMessage');
      const errorMessage = document.getElementById('errorMessage');

      // 初始化事件监听器
      function initEvents() {
        // 图片上传相关事件
        imageUpload.addEventListener('click', (e) => {
          // 只有在没有文件时才触发文件选择
          if (!currentImageFile && e.target === imageUpload) {
            imageInput.click();
          }
        });
        imageUpload.addEventListener('dragover', handleDragOver);
        imageUpload.addEventListener('dragleave', handleDragLeave);
        imageUpload.addEventListener('drop', handleDrop);
        imageInput.addEventListener('change', handleImageSelect);

        // Base64输入事件
        base64Input.addEventListener('input', handleBase64Input);
        base64Input.addEventListener('paste', handleBase64Paste);

        // 按钮事件
        convertToBase64Btn.addEventListener('click', convertImageToBase64);
        convertFromBase64Btn.addEventListener('click', convertBase64ToImage);
        downloadImageBtn.addEventListener('click', downloadDecodedImage);
        clearImageBtn.addEventListener('click', clearImagePanel);
        clearBase64Btn.addEventListener('click', clearBase64Panel);
        copyBase64Btn.addEventListener('click', copyBase64ToClipboard);
        downloadBase64Btn.addEventListener('click', downloadBase64AsFile);
      }

      // 拖拽处理
      function handleDragOver(e) {
        e.preventDefault();
        imageUpload.classList.add('dragover');
      }

      function handleDragLeave(e) {
        e.preventDefault();
        imageUpload.classList.remove('dragover');
      }

      function handleDrop(e) {
        e.preventDefault();
        imageUpload.classList.remove('dragover');
        
        const files = e.dataTransfer.files;
        if (files.length > 0) {
          const file = files[0];
          if (file.type.startsWith('image/')) {
            handleImageFile(file);
          } else {
            showError('❌ 请选择有效的图片文件');
          }
        }
      }

      // 图片选择处理
      function handleImageSelect(e) {
        const file = e.target.files[0];
        if (file) {
          handleImageFile(file);
        }
      }

      // 处理图片文件
      function handleImageFile(file) {
        // 验证文件类型
        if (!file.type.startsWith('image/')) {
          showError('❌ 请选择有效的图片文件');
          return;
        }

        // 验证文件大小（限制10MB）
        if (file.size > 10 * 1024 * 1024) {
          showError('❌ 图片文件过大，请选择小于10MB的文件');
          return;
        }

        currentImageFile = file;
        
        // 显示图片预览
        const reader = new FileReader();
        reader.onload = function(e) {
          showImagePreview(e.target.result, file);
          convertToBase64Btn.disabled = false;
        };
        reader.onerror = function() {
          showError('❌ 读取图片文件失败');
        };
        reader.readAsDataURL(file);

        clearError();
        showStatus('✅ 图片加载成功，可以开始转换');
      }

      // 显示图片预览
      function showImagePreview(src, file) {
        const img = document.createElement('img');
        img.src = src;
        img.className = 'preview-image';
        img.alt = '图片预览';
        
        const fileInfo = document.createElement('div');
        fileInfo.className = 'file-info';
        fileInfo.innerHTML = `
          <div class="file-info-item">
            <span class="file-info-label">文件名：</span>
            <span class="file-info-value">${file.name}</span>
          </div>
          <div class="file-info-item">
            <span class="file-info-label">文件大小：</span>
            <span class="file-info-value">${formatFileSize(file.size)}</span>
          </div>
          <div class="file-info-item">
            <span class="file-info-label">文件类型：</span>
            <span class="file-info-value">${file.type}</span>
          </div>
        `;
        
        imagePreview.innerHTML = '';
        imagePreview.appendChild(img);
        imagePreview.appendChild(fileInfo);
      }

      // Base64输入处理
      function handleBase64Input() {
        const value = base64Input.value.trim();
        convertFromBase64Btn.disabled = value.length === 0;
        
        if (value.length > 0) {
          clearError();
        }
      }

      // Base64粘贴处理
      function handleBase64Paste(e) {
        setTimeout(() => {
          handleBase64Input();
        }, 10);
      }

      // 图片转Base64
      function convertImageToBase64() {
        if (!currentImageFile) {
          showError('❌ 请先选择图片文件');
          return;
        }

        showStatus('🔄 正在转换为Base64编码...');
        convertToBase64Btn.disabled = true;

        const reader = new FileReader();
        reader.onload = function(e) {
          currentBase64 = e.target.result;
          resultBase64.value = currentBase64;
          resultSection.classList.add('show');
          
          showStatus('✅ 转换完成！Base64编码已生成');
          convertToBase64Btn.disabled = false;
        };
        reader.onerror = function() {
          showError('❌ 转换失败，请重试');
          convertToBase64Btn.disabled = false;
        };
        reader.readAsDataURL(currentImageFile);
      }

      // Base64转图片
      function convertBase64ToImage() {
        const base64String = base64Input.value.trim();
        if (!base64String) {
          showError('❌ 请输入Base64编码字符串');
          return;
        }

        showStatus('🔄 正在解码Base64为图片...');
        convertFromBase64Btn.disabled = true;

        try {
          // 处理Base64字符串
          let processedBase64 = base64String;
          
          // 如果不包含data:前缀，尝试自动添加
          if (!processedBase64.startsWith('data:')) {
            // 尝试检测图片类型
            const imageType = detectImageType(processedBase64);
            processedBase64 = `data:image/${imageType};base64,${processedBase64}`;
          }

          // 创建图片元素进行验证
          const img = new Image();
          img.onload = function() {
            // 显示预览
            showBase64Preview(processedBase64, img);
            
            // 转换为Blob用于下载
            fetch(processedBase64)
              .then(res => res.blob())
              .then(blob => {
                decodedImageBlob = blob;
                downloadImageBtn.disabled = false;
                showStatus('✅ 解码成功！图片已生成');
                convertFromBase64Btn.disabled = false;
              })
              .catch(error => {
                showError('❌ 生成下载文件失败');
                convertFromBase64Btn.disabled = false;
              });
          };
          img.onerror = function() {
            showError('❌ Base64编码无效或格式不正确');
            convertFromBase64Btn.disabled = false;
          };
          img.src = processedBase64;
        } catch (error) {
          showError('❌ Base64解码失败：' + error.message);
          convertFromBase64Btn.disabled = false;
        }
      }

      // 显示Base64预览
      function showBase64Preview(src, img) {
        const previewImg = document.createElement('img');
        previewImg.src = src;
        previewImg.className = 'preview-image';
        previewImg.alt = '解码预览';
        
        const fileInfo = document.createElement('div');
        fileInfo.className = 'file-info';
        fileInfo.innerHTML = `
          <div class="file-info-item">
            <span class="file-info-label">图片尺寸：</span>
            <span class="file-info-value">${img.naturalWidth} × ${img.naturalHeight}</span>
          </div>
          <div class="file-info-item">
            <span class="file-info-label">Base64长度：</span>
            <span class="file-info-value">${base64Input.value.length.toLocaleString()} 字符</span>
          </div>
        `;
        
        base64Preview.innerHTML = '';
        base64Preview.appendChild(previewImg);
        base64Preview.appendChild(fileInfo);
      }

      // 检测图片类型
      function detectImageType(base64String) {
        const signatures = {
          '/9j/': 'jpeg',
          'iVBORw0KGgo': 'png',
          'R0lGODlh': 'gif',
          'UklGR': 'webp',
          'Qk': 'bmp'
        };
        
        for (const [signature, type] of Object.entries(signatures)) {
          if (base64String.startsWith(signature)) {
            return type;
          }
        }
        
        return 'png'; // 默认为PNG
      }

      // 下载解码后的图片
      function downloadDecodedImage() {
        if (!decodedImageBlob) {
          showError('❌ 没有可下载的图片');
          return;
        }

        const timestamp = new Date().toISOString().slice(0, 19).replace(/:/g, '-');
        const filename = `decoded_image_${timestamp}.png`;
        
        const a = document.createElement('a');
        a.href = URL.createObjectURL(decodedImageBlob);
        a.download = filename;
        a.click();
        
        URL.revokeObjectURL(a.href);
        showStatus('📥 图片下载中...');
      }

      // 复制Base64到剪贴板
      async function copyBase64ToClipboard() {
        if (!currentBase64) {
          showError('❌ 没有可复制的Base64编码');
          return;
        }

        try {
          await navigator.clipboard.writeText(currentBase64);
          showStatus('📋 Base64编码已复制到剪贴板');
        } catch (error) {
          // 降级方案
          const textArea = document.createElement('textarea');
          textArea.value = currentBase64;
          document.body.appendChild(textArea);
          textArea.select();
          document.execCommand('copy');
          document.body.removeChild(textArea);
          showStatus('📋 Base64编码已复制到剪贴板');
        }
      }

      // 下载Base64为文本文件
      function downloadBase64AsFile() {
        if (!currentBase64) {
          showError('❌ 没有可下载的Base64编码');
          return;
        }

        const timestamp = new Date().toISOString().slice(0, 19).replace(/:/g, '-');
        const filename = `base64_${timestamp}.txt`;
        
        const blob = new Blob([currentBase64], { type: 'text/plain' });
        const a = document.createElement('a');
        a.href = URL.createObjectURL(blob);
        a.download = filename;
        a.click();
        
        URL.revokeObjectURL(a.href);
        showStatus('💾 Base64文件下载中...');
      }

      // 清空图片面板
      function clearImagePanel() {
        currentImageFile = null;
        currentBase64 = '';
        imagePreview.innerHTML = '<p style="color: var(--text-secondary); font-size: 1.1rem;">🖼️ 图片预览区</p>';
        convertToBase64Btn.disabled = true;
        resultSection.classList.remove('show');
        resultBase64.value = '';
        clearStatus();
        clearError();
        // 重置input值，确保可以重新选择文件
        imageInput.value = '';
      }

      // 清空Base64面板
      function clearBase64Panel() {
        decodedImageBlob = null;
        base64Input.value = '';
        base64Preview.innerHTML = '<p style="color: var(--text-secondary); font-size: 1.1rem;">🖼️ 解码预览区</p>';
        convertFromBase64Btn.disabled = true;
        downloadImageBtn.disabled = true;
        clearStatus();
        clearError();
      }

      // 显示状态信息
      function showStatus(message) {
        statusMessage.textContent = message;
        errorMessage.textContent = '';
      }

      // 显示错误信息
      function showError(message) {
        errorMessage.textContent = message;
        statusMessage.textContent = '';
      }

      // 清空状态信息
      function clearStatus() {
        statusMessage.textContent = '';
      }

      // 清空错误信息
      function clearError() {
        errorMessage.textContent = '';
      }

      // 格式化文件大小
      function formatFileSize(bytes) {
        if (bytes === 0) return '0 Bytes';
        const k = 1024;
        const sizes = ['Bytes', 'KB', 'MB', 'GB'];
        const i = Math.floor(Math.log(bytes) / Math.log(k));
        return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
      }

      // 初始化
      initEvents();
    </script>
  </body>
</html>